<%@ page language="java" import="java.util.*" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
 <div class="page-header">
     <h3>Frame相关</h3>
 </div>
<h2>快速开始</h2>
<h4>Frame的结构</h4>
<p>
Frame是以spring为核心构建的快速项目工具。其结构体系如下图所示。frame只包含mvc中的mv,v交给浏览器来实现。所以没有将jspTag或是springTag引入。
Frame的前端并不限定具体的类库。但推荐使用bootstrap和jquery及相关插件
</p>
<img src="frame/about/webstructure.jpg" class="img-rounded"/>
<p>
 在实际使用过程中，一般只需要关注your部分，如：<b>Your Business Beans extends the BaseBean,
 Your Service Layer,Your Controllers extends the BaseService,Your SQL Files</b>

</p>
 <ul>
  <li><b>BaseBean</b></li>
  <p>BaseBean提供的public方法有：toString(),select(),insert(),update(),delete(),args(),
  提供的protected方法 有appender()，protected变量有tableName，args。
  toString方便子类打印自己为字符串形式。
  其他几个方法或变量是关于生成sql语句的，每个方法都只生成简单的单表操作语句。详细情况前参见<a>API</a>文档。在创建业务bean的时候，可以
  通过继承basebean来获得这些功能，或是重写basebean的某些方法来满足自己的需求</p>
  <li><b>BaseService</b></li>
  <p>baseService作为基础服务类设计为被继承。
  提供的服务包含：获取登录系统当前用户的信息。提供一个访问数据库的DAO对象，一个日志记录对象</p>
  <li><b>Your Service Layer</b></li>
  <p>作为经典的3层模型中的服务层当然有其存在的必要性，在实际应用中整个项目执行3层切割的方式未免太过粗暴。
  故Frame摈弃了这种做法。只在该使用的地方使用service层。参见Frame中上传下载部分的代码</p>
  <li><b>SQL Files&DAO</b></li>
  <p>经过观察使用hibernate或是mybatis这样的持久化框架一个DAO层需要写的很复杂或是很庞大，但模式都基本一样：传入对象，肯定要包含sql，sql不是手写也需要工具自动生成。
  Frame抽取统一模式封装为一个DAO对象。结合SQL文件可以将sql语句进行统一管理，配合baseBean自动生成sql，也使整个DAO层得到简化。
  sql文件的编写方式可以参见sys.sql这个文件。</p>
</ul>
 <h4>一个请求的处理流程</h4>
<p>
Frame集成了安全框架shiro。处理浏览器一个请求的基本流程如下图所示。
</p>
<img src="frame/about/webflowc.jpg" class="img-rounded"/>
<p>
frame提供对浏览器请求处理的完整过程。
 当一个请求进入frame时，最先遇到的是frame实现的shiro实例S(只是一个方便叙述的代号而已)。S负责处理所有认证与授权的事情。
 具体处理过程参见frame权限控制。通过考验的请求由frame的mvc部分接管，基本都是spring-mvc功劳，
 请求会被指向唯一的一个Controller方法F来处理，在进入F前，frame会创建一个切面A来做一些参数校验结果检测的的工作。因为参数校验在
 spring-mvc分配任务的时候已经完成，所以A的主要任务就是查看参数校验结果。如果结果是OK,那么这个请求进入F继续前进。
 否则将校验结果组织为一个消息返回。进入F的请求在后续的执行中如果抛出异常，A会全部拿下尽量做记录尽量的构造一个消息返回告诉浏览器。
这个返回的消息为一个消息代码，通过代码可以在前端找到对应的消息内容。有时也返回带参数的消息代码，参数可以用来构造要显示的消息内容。
至此，frame的工作完成。
</p>
<h3>Frame已经提供的功能</h3>
<ul>
  <li>一套简单实用的权限控制逻辑</li>
  <li>登录，登出系统功能</li>
  <li>记录查看controller访问情况的功能</li>
  <li>菜单控制逻辑</li>
  <li>文件上传下载组件</li>
  <li>简单实用的J2EE开发基础。具体后面会相信说明</li>
</ul>

<h4>用户角色</h4>
<p>执行用户角色的增删改查，角色在系统属于用户的一个属性。用来对用户进行分类，做权限相关的控制</p>
<h4>用户分组</h4>
<p>执行用户分组的增删改查，分组在系统属于用户的一个属性，相当于部门属性。用来对用户进行分类，做权限相关的控制。本质上角色和分组是没有区别的。都是对用户的一种分类方式而已。</p>
<h4>用户管理</h4>
<p>执行用户的增删改查操作,为用户分配角色，分组信息。</p>
<h4>资源管理</h4>
<p>执行资源的增删改查操作，资源通过系统内的uri来唯一标识。同时每个资源的uri就是记录的主键。
Frame实现的这套系统资源权限控制逻辑为：以系统资源为核心通过2种分类方式(角色，分组)关联给具体用户。
跟菜单控制没有关系。这样做的好处是可以很方便实现按钮级的权限控制，其实是资源级的。有了资源级的权限控制，再反过来
根据不同用户对菜单指向资源的权限处理就可以在页面上渲染出不同的用户看到不同的菜单的样子了。
理论上把所有菜单都暴露给每个用户也没关系，如果没有权限，点了等于没点。</p>
<h4>字典管理</h4>
<p>Frame对系统的字典管理功能也做了重新设计。作者之前见过的字典管理功能都以数据库表为核心。其实这种东西本来就是数据库设计3大范式的一个产物。
最多系统会考虑某些特殊字典请求比较频繁会将字典表的数据加载到内存缓冲起来，以减少对数据库的请求。实际上这种处理方式能节省多少数据资源，我目前还
没见到相关分析。</p>
<p>Frame因为投靠了移步请求的大旗，故采用了将字典数据缓存到浏览器的处理方式。
具体为主页面载入时，请求加载所有字典信息，并通过$("body").data("codes",codes);进行缓冲。这样有需要进行字典翻译的数据在后台是不需要跟字典表做关联的。
直接将表中的字典code带到前端，然后通过$("body").data("codes");获取对应字典信息进行翻译即可。这样做的好处是减少了数据请求的基础上进一步减少了相关表
的关联查询。有利就有弊，缺点很明显，比如系统集成报表工具之类的东西就很难让这些工具适用这种机制。好在大多数时候都不用这些工具。另外要知道如果只是为了在结果中显示某个值的中文解释去做个表连接真是一件很没意思的事情。</p>
<h4>菜单管理</h4>
<p>Frame的菜单管理功能因为其实现的权限控制逻辑不同也不同于大多数的通过本人用过的SSH集成环境。Frame的菜单管理不涉及任何的权限控制相关的内容。这里只负责对菜单项目进行维护（增删改查）
并将菜单项于其所指向的资源进行关联。而用户所看到的最终菜单结构，则由用户对资源的访问权限决定。</p>
<h3>以上各模块间的关系</h3>
<img src="frame/about/permitionNotice.jpg" class="img-rounded"/>
<p></p>
<h4>日志管理</h4>
<p>用于查看对系统controller资源的访问情况。由spring拦截器实现，具体代码位置在frame.log.LogIntercptor中，
配置信息在WEB-INF/config/framemvc.xml中。同时，该功能可以作为用frame实现安条件查询数据的样例！</p>

<h4>druid监控</h4>
<p>打开druid的监控页面。该功能由druid提供。欲知详情可以百度一下。</p>

<h4>Login/Logout</h4>
<p>退出系统，清除当前session后，将浏览器重定向到登陆页面</p>
<h2>Frame的思考</h2>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<strong>Frame</strong> ，叫<strong>Frame</strong>只是因为这样叫显得简单。有那么多的框架，却没有一个名字叫框架的框架。多遗憾！
像这个名字一样，Frame所传达的思想也是简单，我的目标是简单到这类事情本来的样子。不要因为设计而设计，
如果业务不需要service层，去掉就是了。没必要因为那些假设中的或官方或业界或正式的理由去将代码写的冗长，
去迎合假设中的风险。比如若要跟换数据库怎么办...按照奥卡姆剃刀的哲学这样假设没多大意义。
</p>
<h3>关于Controller</h3>
<p>什么？Action？这是struts时代流行的叫法。当下我们还是叫controller好了。它是mvc模式中c的本来面目。spring-mvc实现优雅使用方便功能强大。frame全部照搬。
关于spring-mvc的使用资料可以百度，也可以参考构建frame的过程中用到的资源。见<a>该项目引用过的资源</a>部分</p>
<h3>关于Service</h3>
<p>作为经典的3层模型中的服务层当然有其存在的必要性，在实际应用中整个项目执行3层切割的方式未免太过粗暴。
  许多地方的业务逻辑根本不会复杂到需要分到3层里面处理。这种单一的3层处理方式有时候还会增加程序员的判断成本，
  即花时间去考虑某段处理代码是放到controller层呢还是service层。而且还会造成好多不必要的代码，比如dao调用的service层。
  所以Frame不建议将整个工程都切为完整的3层。一般的系统大多数时候业务都比较简单，故在controller中就可以直接搞定
只是在必要的时候，才需要service层的引入。比如Frame中的文件的上传功能。另外Frame中的Controller都要继承一个叫做BaseService的抽象类，
这个父类提供一个dao实例，一个logger实例，一个获取当前用户的getUser()方法。dao,logger 都为protected修饰符，子类中直接使用。
这只是将service层弱化到controller层的一种实现方式。具体代码见frame的FrameMgr和Gate这2个controller实现。
</p>

<h3>关于DAO</h3>
 <p>
 关于DAO,dao是什么，一般的ssh框架中这货要独立作为一层，既然是层感觉上就要有好多东西排列到一起被上下挤压所以通常来说，dao 就是很多包含了sql语句的
 java类。字面上来理解，dao的全称是data(或是database) access object你要较真说成是objects也无所谓。这里要说的不是一个数量的区别。
 而是我要问，什么是数据库访问对象？
 度娘说：DAO(Data Access Object)是一个数据访问接口，数据访问：顾名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。
 我认为这货就是个工具，是用来访问数据库的。举个例子，我要去上海，飞机就是个工具，我可以坐着去上海转转，上海是数据库的话，飞机就是面向人的一个访问工具。
 那飞机需要知道我去上海干啥吗?我需要告诉飞机我去干啥吗？当然是NO了。
 在回到dao来，如果一个dao包含了select a,b from atable 这样的语句后还被命名为xxxDao。那么这里sql所表达的意思算不算业务，算不算调用这个dao
 访问数据库的目的。大多数简单的查询业务核心就是select xxx from xtabel,这样的话dao层是不是被业务给污染了。在回到坐飞机的例子，那么xxxDao
 是不是有点专机意思，在以节约资源为准则的计算机世界这样的设计是不是很浪费，那坐飞机的人是不是告诉了飞机他去上海的目的，
 如果是去上海泡妞是不是要写个泡妞dao出来呢。这其实是最求松耦合的过度设计。 </p>
  <p>
这里Frame进行了简化DAO层的实践，目标是一个dao实现负责所有的应用与数据库之间的交互工作。
基于spring-tempelete，Frame提供了单一的DAO对象，后续的开发无需针对DAO做开发，这一块可以省掉一大块工作量。
 要使用这个dao,需要告诉他一个sql语句，希望处理的对象型，希望处理的参数，及参数顺序（sql为更新操作的时候用）。
 <b>还要遵循一个约定，就是应用中所以要入库的数据其变量命名必须和其对应的数据库字段名称一样。(这里体现的是约定优于配置的思想)</b>这样的做的好处是，1系统变量命名统一，
 2节约开发过程中为变量命名的时间（有经验的人都知道，给变量弄响当当的名字不容易啊！），因为这个约定，
 我们可以彻底的丢掉 hibernate,mybatis中的映射文件。
 这里搞成一个dao也是有缺点的，比如实现sql逻辑公用不好搞，为此我将sql语句放在了文本文件中，
 弄了sqlLoader,dao初始化的时候统一搞到内存中。这样sql语句的共用就实现了。
 </p>
 <p>
 为什么不是hibernate，hibernate好吗？第一我很烦写映射文件，第二我很烦写很多dao。第三做批量插入怎么来？我要直接将一个表的数据插入到另外一个表时
 怎么来，类似：insert into atable select x1,x2,x3,x4 from btable b join ctable c on b.id=c.id where b.cc=? and c.dd=?
 这样的语句怎么来？如果select a,b from atable 返回的是一个包含属性a,b的对象好说，如果我还想这个方法同时实现 select a from atable a 是
 字符串，而我只想这样写 String a=ahibernateF(/*select a from atable*/);即这个方法直接返回一个String对象给我，怎么来？我在项目中的经验
 告诉我，hibernate虽好，但很难用好，其学习成本比学好sql语句高多了。sql语句是很优美的，学好也不难相比hibernate来说。
 </p>
 <h3> 消息传输体系&入参校验</h3>
 <p>系统对用户的操作总是需要给出回应的，一般是如何做的呢？直接在java代码中写“操作成功！”或是直接在JavaScript中写“操作成功！”
 总的来说，是在逻辑出现的地方写。这样是最直接的方式，但问题很多。比如不同的开发人员对同样的意思可能表述不一样，有人写“请选择一条记录”有人会写“请选择记录”
多少会有差别。比如要做国际化，提示信息散落在代码各处，不利于统一处理，此外还会造成信息冗余。
 </p>
 <p>Frame提供的解决方案是系统中所有的消息编码。编码消息映射关系放置在浏览器端。在前端统一将消息编码翻译成对应的消息内容。</p>
 <p>
 校验层的实现见这个博客（http://blog.csdn.net/walkerjong/article/details/7210727）这里说的很清楚，感谢walkerJong。
 Frame做的事情是统一处理了校验结果，判断依据是判断被校验的方法入参中是否包含 BindingResult 类型的校验结果，如果有就查看结果中是否有错误，
 如果有，就获取错误原因装配一条消息返回给浏览器，否则程序继续前进。
 所有的逻辑在frame.validateProcessor.DefaultValidateProcessor实现
 </p>
<h3>关于事务控制&异常处理</h3>
<p>Frame提供了最基础的异常处理方式，定义统一的异常FrameException(运行时异常继承了RuntimeException)在controller这一层进行事务控制。
事务控制相关配置见WEB-INF/config/frameContext.xml。异常产生时会在DefaultValidateProcessor中被包装为FrameException再抛出，
最后会在FrameExceptionHandler被拦截进行记录日志，装配返回信息的工作。如果是异步请求返回的消息内容符合Frame的消息传输体系。如果是同步方式会返回一到
一个固定的异常页面。</p>
<h3>关于Model</h3>
<p>model的概念太过理论化，反正大家都习惯使用pojo这样的方式来创建bean。但是Frame尝试去摆脱POJO。因为basebean只是第一步。</p>

 <h3>Frame依赖的开源项目</h3>
 <p>
 <ul>
  <li>frame的mvc由spring-mvc实现</li>
  <li>dao由spring-jdbcTemplet实现</li>
  <li>权限控制部分由shiro实现</li>
  <li>参数校验层由spring-aop+hibernate-validator实现</li>
  <li>缓存由ehcache实现</li>
  <li>数据库连接池由druid实现</li>
  <li>SQL打印由log4jdbc实现</li>
  <li>日志记录是log4j</li>
</ul>
  </p>
 <h3>开发计划</h3>
 <h3>该项目引用过的资源</h3>
 
 <jsp:include page="about/reference.jsp" flush="true" ></jsp:include>
  
